#pragma once
#include <time.h>
#include <vector>
#include <functional>
#include <iostream>


class timer;

#define BUFFER_SIZE 2048
class conndata
{
public:
    int _sockfd;
    char buffer[BUFFER_SIZE] = {0};
    timer *_tr;
};

class timer
{
typedef std::function<void( conndata *)> func_t;
public:
    timer(int rotation,int cur_slot)
        :_rotation(rotation),_cur_slot(cur_slot),_next(nullptr),_prev(nullptr)
    {}
    int _rotation;// 当前圈数
    int _cur_slot;// 当前定时器对应的槽位
    // 回调
    func_t _cb;
    conndata *_conn;// 用户数据
    timer *_next;
    timer *_prev;
};


class timer_wheel
{
public:
    timer_wheel()
        :_wheel(N),_cur_slot(0)// 默认指向第一个槽位
    {}

    // 加一个析构

    timer *add_timer(int timeout)
    {
        if(timeout < 0) return nullptr;

        int ticks = 0;
        if(timeout < 1) ticks = 1;
        else ticks = timeout / TI;// 得到当前定时器需要多少个时间滴答

        int rotation = ticks / N;// 应该在第几圈？
        int slot = (_cur_slot + (ticks % N)) % N;// 除留余数法，得到当前定时器应该在时间轮的哪个槽位
        timer *tr = new timer(rotation,slot);

        if(_wheel[slot] == nullptr) _wheel[slot] = tr;
        else 
        {
            tr->_next = _wheel[slot];
            _wheel[slot]->_prev = tr;
            _wheel[slot] = tr;
        }

        return tr;
    }

    void del_timer(timer *tr)
    {
        if(!tr) return;
        int slot = tr->_cur_slot;
        if(_wheel[slot] == tr)// 如果是槽位头
        {
            _wheel[slot] = _wheel[slot]->_next;
            if(_wheel[slot]) _wheel[slot]->_prev = nullptr;
            delete tr;
            tr = nullptr;
        }
        else 
        {
            tr->_prev->_next = tr->_next;
            if(tr->_next) tr->_next->_prev = tr->_prev;
            delete tr;
            // timer *prev = tr->_prev;
            // timer *next = tr->_next;
            // if(prev) prev->_next = next;
            // if(next) next->_prev = prev;
            // delete tr;
            // tr = nullptr;
        }
    }

    void tick()
    {
        timer *now = _wheel[_cur_slot];// 获取当前槽位的头节点定时器
        while(now)
        {
            if(now->_rotation > 0)// 虽然选中了当中定时器，但是并不是最后一圈，因此不会执行定时任务
            {
                --(now->_rotation);
                now = now->_next;
            }
            else 
            {
                now->_cb(now->_conn);// 执行定时任务
                timer *next = now->_next;
                del_timer(now);
                now = next;
            }
        }
        ++_cur_slot;
        _cur_slot %= N;// 不能越界
    }
protected:
    const static int N = 60;
    const static int TI = 1;// 心博
    std::vector<timer *> _wheel;// 数组模拟时间轮
    int _cur_slot;
};